/**
 * 
 * @Project HRL Simulation
 * @Date 20.06.2011
 * @Author Aebi Pascal, Kocher Marc, Sriranjan George
 * @School BFH-TI Biel, Projekt 1
 *
 */

package gui.views;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.util.Hashtable;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;

import utils.Prop;

import gui.Model;


public class SettingsCardPanel extends JPanel {

	private Model model;
	private int width = 800;
	private int height = 830;
	
	private Dimension dJLabel;
	private Dimension dJTextField;
	private Dimension dJTextFieldLong;
	private Font fCurrent;
	private GridBagConstraints gbc;
	private JPanel jpRandomLoads;
	private JPanel jpAddLoad;
	private JPanel jpLoadsTable;
	private SpinnerNumberModel snmRandomLoadNumber;
	private JSpinner jspLiftNumber;
	private JSpinner jspRackLength;
	private JSpinner jspRackHeight;
	private JSpinner jspRandomLoadNumber;
	private JSlider jslConveyorSpeed;
	private JSlider jslLiftSpeed;
	private JSlider jslSimulationSpeed;
	private JRadioButton jrbManualLoads;
	private JRadioButton jrbRandomLoads;
	private JButton jbAddLoad;
	private JButton jbDeleteAllEntries;
	private JButton jbDeleteSelectedEntries;
	private JButton jbMaxRandomLoads;
	private JButton jbApply;
	private JComboBox jcbInitLiftPosition;
	private JComboBox jcbStrategies;
	private JComboBox jcbLoadType;
	private JCheckBox jcbIn;
	private JCheckBox jcbOut;
	private JCheckBox jcbStore;
	private JTextField jtfLiftSpeed;
	private JTextField jtfConveyorSpeed;
	private JTextField jtfRackNumber;
	private JTextField jtfSimulationSpeed;
	private JTextField jtfLoadName;
	private JTextField jtfClassOfGood;
	private JTextField jtfArrivalTime;
	private JTextArea jtaStrategyDescription;
	private JLabel jlSimulationSpeedUnitText;
	private JTable jtManualLoads;
	private DefaultTableModel dtmManualLoads;
	private String[][] strategies;
	
	
	/**
	 * Creates the settings card panel
	 * 
	 * @param model The model
	 */
	public SettingsCardPanel(Model model) {
		this.model = model;
		
		this.dJLabel = new Dimension(120, 25);
		this.dJTextField = new Dimension(42, 20);
		this.dJTextFieldLong =  new Dimension(90, 20);
		
		this.gbc = new GridBagConstraints();
		this.gbc.weightx = 10;
		this.gbc.weighty = 20;
		this.gbc.gridx = 0;
		this.gbc.gridy = 0;
		this.gbc.anchor = GridBagConstraints.FIRST_LINE_START;
		
		this.setPreferredSize(new Dimension(this.width, this.height));
		
		JPanel jpSystem = this.createSystemPanel();
		this.add(jpSystem);
		
		JPanel jpSpeeds = this.createSpeedsPanel();
		this.add(jpSpeeds);
		
		JPanel jpStrategy = this.createStrategyPanel();
		this.add(jpStrategy);
		
		JPanel jpLoads = this.createLoadsPanel();
		this.add(jpLoads);
		
		JPanel jpButtons = this.createButtonPanel();
		this.add(jpButtons);
		
		this.init();
	}


	/**
	 * Creates the system panel
	 * 
	 * @return The system panel
	 */
	private JPanel createSystemPanel() {
		// Create system panel
		JPanel jpSystem = new JPanel(new GridBagLayout());
		jpSystem.setPreferredSize(new Dimension(232, 190));
		TitledBorder tbSystemSetting = new TitledBorder(new EtchedBorder(), " System ");
		jpSystem.setBorder(tbSystemSetting);
		
		
		// Create lift number label
		JLabel jlLiftNumber = new JLabel("Number of lifts:");
		jlLiftNumber.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(0, 7, 0, 0);
        jpSystem.add(jlLiftNumber, this.gbc);
        
        // Create lift number spinner
        this.jspLiftNumber = new JSpinner(new SpinnerNumberModel(1, 1, 10, 1));
        JSpinner.NumberEditor jspNumberEditor = new JSpinner.NumberEditor(this.jspLiftNumber);
		jspNumberEditor.getTextField().setEditable(false);
		jspNumberEditor.getTextField().setBackground(Color.white);
		jspLiftNumber.setEditor(jspNumberEditor);
		gbc.insets = new Insets(2, 170, 0, 0);
		jpSystem.add(this.jspLiftNumber, this.gbc);
        
		
		// Create rack number label
	    JLabel jlRackNumber = new JLabel("Number of racks:");
        jlRackNumber.setPreferredSize(this.dJLabel);
        this.gbc.insets = new Insets(32, 7, 0, 0);
        jpSystem.add(jlRackNumber, this.gbc);
	    
	    // Create rack number text field
	    this.jtfRackNumber = new JTextField();
        this.jtfRackNumber.setHorizontalAlignment(JTextField.CENTER);
        this.jtfRackNumber.setPreferredSize(this.dJTextField);
        Font curFont = this.jtfRackNumber.getFont();
        this.jtfRackNumber.setFont(new Font(curFont.getFontName(), Font.BOLD, curFont.getSize()));
        this.jtfRackNumber.setEditable(false);
        this.jtfRackNumber.setBackground(Color.white);
        this.gbc.insets = new Insets(34, 170, 0, 0);
        jpSystem.add(this.jtfRackNumber, this.gbc);

        
		// Create rack length label
		JLabel jlRackLength = new JLabel("Length of racks:");
		jlRackLength.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(64, 7, 0, 0);
		jpSystem.add(jlRackLength, this.gbc);
		
		// Create rack length spinner
		this.jspRackLength = new JSpinner(new SpinnerNumberModel(1, 1, 10, 1));
		jspNumberEditor = new JSpinner.NumberEditor(this.jspRackLength);
		jspNumberEditor.getTextField().setEditable(false);
		jspNumberEditor.getTextField().setBackground(Color.white);
		jspRackLength.setEditor(jspNumberEditor);
		gbc.insets = new Insets(66, 170, 0, 0);
		jpSystem.add(this.jspRackLength, this.gbc);
		jspNumberEditor = null;
		
		 // Create rack height label
        JLabel jlHeight = new JLabel("Height of racks:");
		jlHeight.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(96, 7, 0, 0);
        jpSystem.add(jlHeight, this.gbc);
        
        // Create rack height spinner
		this.jspRackHeight = new JSpinner(new SpinnerNumberModel(1, 1, 10, 1));
		jspNumberEditor = new JSpinner.NumberEditor(this.jspRackHeight);
		jspNumberEditor.getTextField().setEditable(false);
		jspNumberEditor.getTextField().setBackground(Color.white);
		jspRackHeight.setEditor(jspNumberEditor);
		this.gbc.insets = new Insets(98, 170, 0, 0);
		jpSystem.add(this.jspRackHeight, this.gbc);
		
		
		// Create initial lift position label
		JLabel jlInitLiftPosition = new JLabel("Initial lift position:");
		jlInitLiftPosition.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(128, 7, 0, 0);
        jpSystem.add(jlInitLiftPosition, this.gbc);
        
        // Create initial lift position combo box
	    this.jcbInitLiftPosition = new JComboBox(this.model.getsArrayLiftInitPosition());
	    this.gbc.insets = new Insets(130, 143, 0, 0);
	    jpSystem.add(this.jcbInitLiftPosition, this.gbc);
	    
	    return jpSystem;
	}


	/**
	 * Creates the speeds panel
	 * 
	 * @return The speeds panel
	 */
	private JPanel createSpeedsPanel() {
		// Create speeds panel
		JPanel jpSpeeds = new JPanel(new GridBagLayout());
		jpSpeeds.setPreferredSize(new Dimension(543, 190));
		TitledBorder tbSpeedsSetting = new TitledBorder(new EtchedBorder(), " Speeds ");
		jpSpeeds.setBorder(tbSpeedsSetting);
		
		
		// Create hash table for conveyor and lift speed sliders
		Hashtable<Integer, JLabel> labelTableSliders = new Hashtable<Integer, JLabel>();
		labelTableSliders.put(new Integer(1), new JLabel("Min"));
		labelTableSliders.put(new Integer(5), new JLabel("Normal"));
		labelTableSliders.put(new Integer(9), new JLabel("Max"));
		
		
		// Create conveyor speed label
		JLabel jlConveyorSpeedText = new JLabel("Conveyor speed:");
		jlConveyorSpeedText.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(2, 7, 0, 0);
		jpSpeeds.add(jlConveyorSpeedText, this.gbc);
		
		// Create conveyor speed slider
		this.jslConveyorSpeed = new JSlider(1, 9);
		this.jslConveyorSpeed.setLabelTable(labelTableSliders);
		this.jslConveyorSpeed.setMajorTickSpacing(4);
		this.jslConveyorSpeed.setMinorTickSpacing(1);
		this.jslConveyorSpeed.setPaintLabels(true);
		this.jslConveyorSpeed.setPaintTicks(true);
		this.jslConveyorSpeed.setSnapToTicks(true);
		this.gbc.insets = new Insets(0, 150, 0, 0);
		jpSpeeds.add(this.jslConveyorSpeed, this.gbc);
		
		 // Create conveyor speed text field
	    this.jtfConveyorSpeed = new JTextField();
        this.jtfConveyorSpeed.setHorizontalAlignment(JTextField.CENTER);
        this.jtfConveyorSpeed.setPreferredSize(this.dJTextField);
        this.fCurrent = this.jtfConveyorSpeed.getFont();
        this.jtfConveyorSpeed.setFont(new Font(this.fCurrent.getFontName(), Font.BOLD, this.fCurrent.getSize()));
        this.jtfConveyorSpeed.setEditable(false);
        this.jtfConveyorSpeed.setBackground(Color.white);
        this.gbc.insets = new Insets(0, 378, 0, 0);
        jpSpeeds.add(this.jtfConveyorSpeed, this.gbc);
		
		// Create conveyor speed unit label
		JLabel jlConveyorSpeedUnitText = new JLabel("fields per second");
		this.gbc.insets = new Insets(2, 427, 0, 0);
		jpSpeeds.add(jlConveyorSpeedUnitText, this.gbc);
		

		// Create lift speed label
		JLabel jlLiftSpeedText = new JLabel("Lift speed:");
		jlLiftSpeedText.setPreferredSize(this.dJLabel);
		this.gbc.insets = new Insets(59, 7, 0, 0);
		jpSpeeds.add(jlLiftSpeedText, this.gbc);
		
		// Create lift speed slider
		this.jslLiftSpeed = new JSlider(1, 9);
		this.jslLiftSpeed.setLabelTable(labelTableSliders);
		this.jslLiftSpeed.setMajorTickSpacing(4);
		this.jslLiftSpeed.setMinorTickSpacing(1);
		this.jslLiftSpeed.setPaintLabels(true);
		this.jslLiftSpeed.setPaintTicks(true);
		this.jslLiftSpeed.setSnapToTicks(true);
		this.gbc.insets = new Insets(57, 150, 0, 0);
		jpSpeeds.add(this.jslLiftSpeed, this.gbc);
		
		 // Create lift speed text field
	    this.jtfLiftSpeed = new JTextField();
        this.jtfLiftSpeed.setHorizontalAlignment(JTextField.CENTER);
        this.jtfLiftSpeed.setPreferredSize(this.dJTextField);
        this.fCurrent = this.jtfLiftSpeed.getFont();
        this.jtfLiftSpeed.setFont(new Font(this.fCurrent.getFontName(), Font.BOLD, this.fCurrent.getSize()));
        this.jtfLiftSpeed.setEditable(false);
        this.jtfLiftSpeed.setBackground(Color.white);
        this.gbc.insets = new Insets(57, 378, 0, 0);
        jpSpeeds.add(this.jtfLiftSpeed, this.gbc);
        
        // Create lift speed unit label
        JLabel jlLiftSpeedUnitText = new JLabel("fields per second");
        this.gbc.insets = new Insets(59, 427, 0, 0);
        jpSpeeds.add(jlLiftSpeedUnitText, this.gbc);

        
		// Create simulation speed label
		JLabel jlSimulationSpeedText = new JLabel("Simulation speed:");
		jlSimulationSpeedText.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(116, 7, 0, 0);
		jpSpeeds.add(jlSimulationSpeedText, this.gbc);
		
		// Create simulation speed slider
		this.jslSimulationSpeed = new JSlider(1, 9);
		this.jslSimulationSpeed.setLabelTable(labelTableSliders);
		this.jslSimulationSpeed.setMajorTickSpacing(4);
		this.jslSimulationSpeed.setMinorTickSpacing(1);
		this.jslSimulationSpeed.setPaintLabels(true);
		this.jslSimulationSpeed.setPaintTicks(true);
		this.gbc.insets = new Insets(114, 150, 0, 0);
		jpSpeeds.add(this.jslSimulationSpeed, this.gbc);
		
		 // Create simulation speed text field
	    this.jtfSimulationSpeed = new JTextField();
        this.jtfSimulationSpeed.setHorizontalAlignment(JTextField.CENTER);
        this.jtfSimulationSpeed.setPreferredSize(dJTextField);
        this.fCurrent = this.jtfSimulationSpeed.getFont();
        this.jtfSimulationSpeed.setFont(new Font(this.fCurrent.getFontName(), Font.BOLD, this.fCurrent.getSize()));
        this.jtfSimulationSpeed.setEditable(false);
        this.jtfSimulationSpeed.setBackground(Color.white);
        this.gbc.insets = new Insets(114, 378, 0, 0);
        jpSpeeds.add(this.jtfSimulationSpeed, this.gbc);
        
        // Create simulation speed unit label
		this.jlSimulationSpeedUnitText = new JLabel("normal speed");
		this.gbc.insets = new Insets(116, 427, 0, 0);
		jpSpeeds.add(this.jlSimulationSpeedUnitText, this.gbc);
		
		return jpSpeeds;
	}


	/**
	 * Creates the strategy panel
	 * 
	 * @return The strategy panel
	 */
	private JPanel createStrategyPanel() {
		// Create strategy panel
		JPanel jpStrategy = new JPanel(new GridBagLayout());
		jpStrategy.setPreferredSize(new Dimension(this.width-20, 162));
		TitledBorder tbSystemStrategy = new TitledBorder(new EtchedBorder(), " Strategy ");
		jpStrategy.setBorder(tbSystemStrategy);
		
		
		// Create strategy selection label
		JLabel jlStrategySelection = new JLabel("Select a strategy:");
		jlStrategySelection.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(0, 7, 0, 0);
		jpStrategy.add(jlStrategySelection, this.gbc);
		
		// Create strategy selection combo box
		this.jcbStrategies = new JComboBox();
		this.strategies = this.model.getStrategies();
		this.jcbStrategies.addItem(strategies[0][0]);
		this.jcbStrategies.addItem(strategies[1][0]);
		this.jcbStrategies.addItem(strategies[2][0]);
		this.jcbStrategies.addItem(strategies[3][0]);
		this.gbc.insets = new Insets(0, 155, 0, 0);
		jpStrategy.add(this.jcbStrategies, this.gbc);
		
		
		// Create strategy description label
		JLabel jlStrategyDescription = new JLabel("Strategy description:");
		jlStrategyDescription.setPreferredSize(dJLabel);
		jlStrategyDescription.setOpaque(true);
		this.gbc.insets = new Insets(37, 7, 0, 0);
		jpStrategy.add(jlStrategyDescription, this.gbc);
		
		// Create strategy description text area
		this.jtaStrategyDescription = new JTextArea();
		this.jtaStrategyDescription.setPreferredSize(new Dimension(606, 90));
		this.jtaStrategyDescription.setEditable(false);
		this.jtaStrategyDescription.setBackground(Color.white);
		this.jtaStrategyDescription.setLineWrap(true);
		this.jtaStrategyDescription.setWrapStyleWord(true);
		this.jtaStrategyDescription.setBorder(this.jtfRackNumber.getBorder());
		this.fCurrent = this.jtaStrategyDescription.getFont();
		this.jtaStrategyDescription.setFont(new Font(fCurrent.getFontName(), Font.BOLD, fCurrent.getSize()));
		this.jtaStrategyDescription.setMargin(new Insets(2, 5, 5, 5));
		this.gbc.insets = new Insets(37, 155, 0, 0);
		jpStrategy.add(this.jtaStrategyDescription, this.gbc);

		return jpStrategy;
	}


	/**
	 * Creates the loads panel
	 * 
	 * @return The loads panel
	 */
	private JPanel createLoadsPanel() {
		// Create load panel
		JPanel jpLoads = new JPanel(new GridBagLayout());
		jpLoads.setPreferredSize(new Dimension(this.width-20, 364));
		TitledBorder tbSystemLoads = new TitledBorder(new EtchedBorder(), " Loads ");
		jpLoads.setBorder(tbSystemLoads);
		
		
		// Create load creation label
		JLabel jlLoadCreationText = new JLabel("Load creation:");
		jlLoadCreationText.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(3, 7, 0, 0);
		jpLoads.add(jlLoadCreationText, this.gbc);
		
		
		// Create radio button group and group radio buttons
		ButtonGroup bgLoadGeneration = new ButtonGroup();
		
		// Create random radio button
		this.jrbRandomLoads = new JRadioButton("Generate loads randomly");
		this.gbc.insets = new Insets(0, 120, 0, 0);
		jpLoads.add(this.jrbRandomLoads, this.gbc);
		bgLoadGeneration.add(this.jrbRandomLoads);
		
		// Create manual radio button
		this.jrbManualLoads = new JRadioButton("Generate loads manually");
		this.gbc.insets = new Insets(0, 310, 0, 0);
		jpLoads.add(this.jrbManualLoads, this.gbc);
		bgLoadGeneration.add(this.jrbManualLoads);
		
		
		// Create random load panel
		this.jpRandomLoads = new JPanel(new GridBagLayout());
		this.jpRandomLoads.setPreferredSize(new Dimension(this.width-42, 61));
		this.gbc.insets = new Insets(30, 5, 0, 0);
		jpLoads.add(this.jpRandomLoads, this.gbc);
		TitledBorder tbRandomLoads = new TitledBorder(new EtchedBorder(), " Random loads ");
		this.jpRandomLoads.setBorder(tbRandomLoads);
		
		
		// Create random load number label
		JLabel jlRandomLoadNumber = new JLabel("Number of random loads:");
		this.gbc.insets = new Insets(4, 7, 0, 0);
		this.jpRandomLoads.add(jlRandomLoadNumber, this.gbc);
		
		// Create random load number spinner
		this.snmRandomLoadNumber = new SpinnerNumberModel(1, 1, null, 1);
		this.jspRandomLoadNumber = new JSpinner(this.snmRandomLoadNumber);
		this.jspRandomLoadNumber.setPreferredSize(new Dimension(52, 20));
		JSpinner.NumberEditor jspNumberEditor = new JSpinner.NumberEditor(this.jspRandomLoadNumber);
		jspNumberEditor.getTextField().setEditable(false);
		jspNumberEditor.getTextField().setBackground(Color.white);
		this.jspRandomLoadNumber.setEditor(jspNumberEditor);
		this.gbc.insets = new Insets(3, 200, 0, 0);
		this.jpRandomLoads.add(this.jspRandomLoadNumber, this.gbc);
		
		// Create max random loads button
		this.jbMaxRandomLoads = new JButton("Set max");
		this.gbc.insets = new Insets(0, 270, 0, 0);
		this.jpRandomLoads.add(this.jbMaxRandomLoads, this.gbc);
		
		// Create random load number label
		JLabel jlOnlySelectedLoadStates = new JLabel("Generate only:");
		this.gbc.insets = new Insets(4, 380, 0, 0);
		this.jpRandomLoads.add(jlOnlySelectedLoadStates, this.gbc);
		
		// Create check box only in loads
		this.jcbIn = new JCheckBox("IN");
		this.gbc.insets = new Insets(0, 475, 0, 0);
		this.jpRandomLoads.add(this.jcbIn, this.gbc);
		
		// Create check box only out loads
		this.jcbOut = new JCheckBox("OUT");
		this.gbc.insets = new Insets(0, 535, 0, 0);
		this.jpRandomLoads.add(this.jcbOut, this.gbc);
		
		// Create check box only store loads
		this.jcbStore = new JCheckBox("STORE");
		this.gbc.insets = new Insets(0, 595, 0, 0);
		this.jpRandomLoads.add(this.jcbStore, this.gbc);
		
		
		// Create manual load panel
		JPanel jpManualLoads = new JPanel(new GridBagLayout());
		jpManualLoads.setPreferredSize(new Dimension(this.width-42, 235));
		this.gbc.insets = new Insets(96, 5, 0, 0);
		jpLoads.add(jpManualLoads, this.gbc);
		TitledBorder tbManualLoads = new TitledBorder(new EtchedBorder(), " Manual loads ");
		jpManualLoads.setBorder(tbManualLoads);
		
		
		// Create load add panel
		this.jpAddLoad = new JPanel(new GridBagLayout());
		this.jpAddLoad.setPreferredSize(new Dimension(200, 200));
		this.gbc.insets = new Insets(0, 0, 0, 0);
		jpManualLoads.add(this.jpAddLoad, this.gbc);
		
		
		// Create load name label
		JLabel jlLoadName = new JLabel("Load name:");
		jlLoadName.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(3, 6, 0, 0);
		this.jpAddLoad.add(jlLoadName, this.gbc);
	    
	    // Create load name number text field
		this.jtfLoadName = new JTextField();
		this.jtfLoadName.setPreferredSize(dJTextFieldLong);
        fCurrent = this.jtfLoadName.getFont();
        this.jtfLoadName.setFont(new Font(fCurrent.getFontName(), Font.BOLD, fCurrent.getSize()));
        this.jtfLoadName.setBackground(Color.white);
        this.gbc.insets = new Insets(5, 100, 0, 0);
        this.jpAddLoad.add(this.jtfLoadName, this.gbc);
		
		
        // Create class of good label
		JLabel jlClassOfGood = new JLabel("Class of good:");
		jlClassOfGood.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(35, 6, 0, 0);
		this.jpAddLoad.add(jlClassOfGood, this.gbc);
	    
	    // Create load name number text field
		this.jtfClassOfGood = new JTextField();
		this.jtfClassOfGood.setPreferredSize(dJTextFieldLong);
        fCurrent = this.jtfClassOfGood.getFont();
        this.jtfClassOfGood.setFont(new Font(fCurrent.getFontName(), Font.BOLD, fCurrent.getSize()));
        this.jtfClassOfGood.setBackground(Color.white);
        this.gbc.insets = new Insets(37, 100, 0, 0);
        this.jpAddLoad.add(this.jtfClassOfGood, this.gbc);
        
        
        // Create state label
		JLabel jlLoadState = new JLabel("Load state:");
		jlLoadState.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(70, 6, 0, 0);
		this.jpAddLoad.add(jlLoadState, this.gbc);
	
		// Create load state combo box
		this.jcbLoadType = new JComboBox(this.model.getLoadStates());
		this.gbc.insets = new Insets(69, 122, 0, 0);
		this.jpAddLoad.add(this.jcbLoadType, this.gbc);
		
		
		// Create arrival time label
		JLabel jlArrivalTime = new JLabel("Arrival time:");
		jlArrivalTime.setPreferredSize(dJLabel);
		this.gbc.insets = new Insets(104, 6, 0, 0);
		this.jpAddLoad.add(jlArrivalTime, this.gbc);
	    
	    // Create arrival time text field
	    this.jtfArrivalTime = new JTextField();
	    this.jtfArrivalTime.setPreferredSize(dJTextFieldLong);
        fCurrent = this.jtfArrivalTime.getFont();
        this.jtfArrivalTime.setFont(new Font(fCurrent.getFontName(), Font.BOLD, fCurrent.getSize()));
        this.jtfArrivalTime.setBackground(Color.white);
        this.gbc.insets = new Insets(106, 100, 0, 0);
        this.jpAddLoad.add(this.jtfArrivalTime, this.gbc);
		
        
        // Create add button
		this.jbAddLoad = new JButton("Add load");
		this.gbc.insets = new Insets(140, 58, 0, 0);
		this.jpAddLoad.add(this.jbAddLoad, this.gbc);
		
		
		// Create table panel
		this.jpLoadsTable = new JPanel();
		this.jpLoadsTable.setPreferredSize(new Dimension(this.width-268, 200));
		this.gbc.insets = new Insets(0, 207, 0, 0);
		jpManualLoads.add(this.jpLoadsTable, this.gbc);
		
		// Create scroll pane for loads table
		this.dtmManualLoads = new DefaultTableModel(){
		    public boolean isCellEditable(int rowIndex, int mColIndex) {
		        return false;
		    }
		};
		
		for(int i=0; i<this.model.getTableHeaderManualLoads().length; i++){
			this.dtmManualLoads.addColumn(this.model.getTableHeaderManualLoads()[i]);
		}

		this.jtManualLoads = new JTable(this.dtmManualLoads);
		this.jtManualLoads.getTableHeader().setReorderingAllowed(false);
		
		JScrollPane jspLoads = new JScrollPane(this.jtManualLoads);
		jspLoads.setPreferredSize(new Dimension(this.width-268, 164));
		this.jpLoadsTable.add(jspLoads);

		
		// Create delete selected entry button
		this.jbDeleteSelectedEntries = new JButton("Delete selected entries");
		this.jpLoadsTable.add(this.jbDeleteSelectedEntries);
		
		// Create delete all entries button
		this.jbDeleteAllEntries = new JButton("Delete all entries");
		this.jpLoadsTable.add(this.jbDeleteAllEntries);
		
		return jpLoads;
	}


	/**
	 * Creates the button panel
	 * 
	 * @return The button panel
	 */
	private JPanel createButtonPanel() {
		// Create button panel
		JPanel jpButton = new JPanel();
		// Create start button
		this.jbApply = new JButton("Apply settings");
		jpButton.add(this.jbApply);
		
		return jpButton;
	}

	
	/**
	 * Initializes the panel with a default view
	 */
	private void init(){
		// Set calculated rack number in text field
		Integer liftNumber = (Integer) this.jspLiftNumber.getValue();
		this.jtfRackNumber.setText(this.model.calculateRackNumber(liftNumber).toString());
		
		// Set standard initial lift position
	    this.jcbInitLiftPosition.setSelectedIndex(1);
	    
		// Calculate conveyor speed
	    Integer iConveyorSpeed = (Integer) this.jslConveyorSpeed.getValue();
	    this.jtfConveyorSpeed.setText(iConveyorSpeed.toString());
	    
        // Calculate lift speed
	    Integer iLiftSpeed = (Integer) this.jslLiftSpeed.getValue();
	    this.jtfLiftSpeed.setText(iLiftSpeed.toString());
        
        // Calculate simulation speed
	    this.jtfSimulationSpeed.setText("");
	    
		// Set standard strategy values
	    this.jtaStrategyDescription.setText(this.strategies[0][1]);
	    
	    // Set calculated maximum random load value
	    Integer rackNumber = model.calculateRackNumber(liftNumber);
	    Integer rackLength = (Integer) this.jspRackLength.getValue();
	    Integer rackHeight = (Integer) this.jspRackHeight.getValue();
	    this.snmRandomLoadNumber.setMaximum(this.model.calculateMaxRandomLoadNumber(rackNumber, rackLength, rackHeight));
	    
		// Set random radio button as standard load creation method and disable manual load panel
		this.jrbRandomLoads.setSelected(true);
		this.enableRandomLoadPanel();
		
		// Disable check box only out loads
		this.jcbOut.setEnabled(false);
	}
	
	
	/**
	 * Enables all components on the random load panel and disables all components on the manual load panel
	 */
	public void enableRandomLoadPanel() {
		Component[] components = this.getJpAddLoad().getComponents();
		for (Component component : components) {
			component.setEnabled(false);
		}
		components = this.getJpLoadsTable().getComponents();
		for (Component component : components) {
			component.setEnabled(false);
		}
		components = this.getJpRandomLoads().getComponents();
		for (Component component : components) {
			component.setEnabled(true);
		}
	}
	
	
	/**
	 * Enables all components on the manual load panel and disables all components on the random load panel
	 */
	public void enableManualLoadPanel(){
		Component[] components = this.getJpRandomLoads().getComponents();
		for (Component component : components) {
			component.setEnabled(false);
		}
		components = this.getJpAddLoad().getComponents();
		for (Component component : components) {
			component.setEnabled(true);
		}
		components = this.getJpLoadsTable().getComponents();
		for (Component component : components) {
			component.setEnabled(true);
		}
	}
	
	
	/**
	 * Gets the current values form the GUI and sets them in the properties file
	 */
	public void getPropertyValues(){
		// System
		this.model.getProperties().setProperty(Prop.LIFT_NUMBER, this.jspLiftNumber.getValue().toString());
		this.model.getProperties().setProperty(Prop.RACK_LENGTH, this.jspRackLength.getValue().toString());
		this.model.getProperties().setProperty(Prop.RACK_HEIGHT, this.jspRackHeight.getValue().toString());
		Integer iSelctedLiftInitPosition = this.jcbInitLiftPosition.getSelectedIndex();
		this.model.getProperties().setProperty(Prop.LIFT_INIT_POSITION, iSelctedLiftInitPosition.toString());
		
		// Speeds
		Integer iConveyorSpeed = this.jslConveyorSpeed.getValue();
		this.model.getProperties().setProperty(Prop.CONVEYOR_SPEED, this.model.convertSliderSpeeds(iConveyorSpeed).toString());
		Integer iLiftSpeed =  this.jslLiftSpeed.getValue();
		this.model.getProperties().setProperty(Prop.LIFT_SPEED, this.model.convertSliderSpeeds(iLiftSpeed).toString());
		Integer iSimulationSpeed = this.jslSimulationSpeed.getValue();
		this.model.getProperties().setProperty(Prop.SIMULATION_SPEED, iSimulationSpeed.toString());
		
		// Strategy
		Integer iSelectedStrategy = this.jcbStrategies.getSelectedIndex();
		this.model.getProperties().setProperty(Prop.STRATEGY, iSelectedStrategy.toString());
		if(this.jcbIn.isSelected()){
			this.model.getProperties().setProperty(Prop.IN_LOADS, "1");
		}
		else{
			this.model.getProperties().setProperty(Prop.IN_LOADS, "0");
		}
		if(this.jcbOut.isSelected()){
			this.model.getProperties().setProperty(Prop.OUT_LOADS, "1");
		}
		else{
			this.model.getProperties().setProperty(Prop.OUT_LOADS, "0");
		}
		if(this.jcbStore.isSelected()){
			this.model.getProperties().setProperty(Prop.STORE_LOADS, "1");
		}
		else{
			this.model.getProperties().setProperty(Prop.STORE_LOADS, "0");
		}
		
		// Loads
		if(this.jrbRandomLoads.isSelected()){
			this.model.getProperties().setProperty(Prop.RANDOM_LOADS, "1");
		}
		else{
			this.model.getProperties().setProperty(Prop.RANDOM_LOADS, "0");
		}
		this.model.getProperties().setProperty(Prop.RANDOM_LOAD_NUMBER, this.jspRandomLoadNumber.getValue().toString());
	}
	
	
	/**
	 * Sets the current values form the properties file in the GUI
	 */
	public void setPropertyValues(){
		// System
		this.jspLiftNumber.setValue(Prop.getInt(Prop.LIFT_NUMBER));
		this.jspRackLength.setValue(Prop.getInt(Prop.RACK_LENGTH));
		this.jspRackHeight.setValue(Prop.getInt(Prop.RACK_HEIGHT));
        // Initial Lift position
        if(Prop.getInt("LIFT_INIT_POSITION") == 0){
        	// Top
        	this.jcbInitLiftPosition.setSelectedIndex(0);
        }
        else if(Prop.getInt("LIFT_INIT_POSITION") == 1){
        	// Middle
        	this.jcbInitLiftPosition.setSelectedIndex(1);
        }
        else if(Prop.getInt("LIFT_INIT_POSITION") == 2){
        	// Bottom
        	this.jcbInitLiftPosition.setSelectedIndex(2);
        }
        
        // Speeds
        this.jslConveyorSpeed.setValue(this.model.convertSliderSpeeds(Prop.getInt(Prop.CONVEYOR_SPEED)));
        this.jslLiftSpeed.setValue(this.model.convertSliderSpeeds(Prop.getInt(Prop.LIFT_SPEED)));
        this.jslSimulationSpeed.setValue(Prop.getInt(Prop.SIMULATION_SPEED));
        
        // Strategy
        if(Prop.getInt("STRATEGY") == 0){
        	jcbStrategies.setSelectedIndex(0);
    		this.jtaStrategyDescription.setText(this.model.getStrategies()[0][1]);
        }
        else if(Prop.getInt("STRATEGY") == 1){
        	jcbStrategies.setSelectedIndex(1);
    		this.jtaStrategyDescription.setText(this.model.getStrategies()[1][1]);
        }
        else if(Prop.getInt("STRATEGY") == 2){
        	jcbStrategies.setSelectedIndex(2);
    		this.jtaStrategyDescription.setText(this.model.getStrategies()[2][1]);
        }
        else if(Prop.getInt("STRATEGY") == 3){
        	jcbStrategies.setSelectedIndex(3);
    		this.jtaStrategyDescription.setText(this.model.getStrategies()[3][1]);
        }
	    if(Prop.getInt("IN_LOADS") == 0){
	    	this.jcbIn.setSelected(false);
	    }
	    else{
	    	this.jcbIn.setSelected(true);
	    }
	    if(Prop.getInt("OUT_LOADS") == 0){
	    	this.jcbOut.setSelected(false);
	    }
	    else{
	    	this.jcbOut.setSelected(true);
	    }
	    if(Prop.getInt("STORE_LOADS") == 0){
	    	this.jcbStore.setSelected(false);
	    }
	    else{
	    	this.jcbStore.setSelected(true);
	    }
        
        // Load creation
        if(Prop.getInt("RANDOM_LOADS") == 0){
        	this.jrbManualLoads.setSelected(true);
        	this.enableManualLoadPanel();
        }
        else{
        	this.jrbRandomLoads.setSelected(true);
        	this.enableRandomLoadPanel();
        }
        this.jspRandomLoadNumber.setValue(Prop.getInt(Prop.RANDOM_LOAD_NUMBER));
	}


	/**
	 * 
	 */
	public void addSettingsActionListener(ActionListener listener) {
		this.jrbRandomLoads.addActionListener(listener);
		this.jrbManualLoads.addActionListener(listener);
		this.jbMaxRandomLoads.addActionListener(listener);
		this.jbAddLoad.addActionListener(listener);
		this.jbDeleteSelectedEntries.addActionListener(listener);
		this.jbDeleteAllEntries.addActionListener(listener);
		this.jbApply.addActionListener(listener);
	}
	
	
	/**
	 * 
	 */
	public void addSettingsChangeListener(ChangeListener listener){
		this.jspLiftNumber.addChangeListener(listener);
		this.jspRackLength.addChangeListener(listener);
		this.jspRackHeight.addChangeListener(listener);
		this.jspRandomLoadNumber.addChangeListener(listener);
		this.jslConveyorSpeed.addChangeListener(listener);
		this.jslLiftSpeed.addChangeListener(listener);
		this.jslSimulationSpeed.addChangeListener(listener);
	}
	
	
	/**
	 * 
	 */
	public void addSettingsItemListener(ItemListener listener){
		this.jcbInitLiftPosition.addItemListener(listener);
		this.jcbStrategies.addItemListener(listener);
		this.jcbLoadType.addItemListener(listener);
		this.jcbIn.addItemListener(listener);
		this.jcbStore.addItemListener(listener);
	}

	
	//getter and setters --------------------------------------------------
	
	
	public JSpinner getJspLiftNumber() {
		return jspLiftNumber;
	}


	public JSpinner getJspRackLength() {
		return jspRackLength;
	}


	public JSpinner getJspRackHeight() {
		return jspRackHeight;
	}


	public JSpinner getJspRandomLoadNumber() {
		return jspRandomLoadNumber;
	}


	public JSlider getJslConveyorSpeed() {
		return jslConveyorSpeed;
	}


	public JSlider getJslLiftSpeed() {
		return jslLiftSpeed;
	}


	public JSlider getJslSimulationSpeed() {
		return jslSimulationSpeed;
	}


	public JRadioButton getJrbManualLoads() {
		return jrbManualLoads;
	}


	public JRadioButton getJrbRandomLoads() {
		return jrbRandomLoads;
	}


	public JComboBox getJcbInitLiftPosition() {
		return jcbInitLiftPosition;
	}


	public JComboBox getJcbStrategies() {
		return jcbStrategies;
	}


	public JComboBox getJcbLoadType() {
		return jcbLoadType;
	}


	public JButton getJbApplySettings() {
		return jbApply;
	}


	public JButton getJbAddLoad() {
		return jbAddLoad;
	}


	public JButton getJbDeleteAllEntries() {
		return jbDeleteAllEntries;
	}


	public JButton getJbDeleteSelectedEntries() {
		return jbDeleteSelectedEntries;
	}


	public JButton getJbMaxRandomLoads() {
		return jbMaxRandomLoads;
	}
	
	
	public JTextField getJtfRackNumber() {
		return jtfRackNumber;
	}
	

	public JPanel getJpRandomLoads() {
		return jpRandomLoads;
	}

	
	public JPanel getJpAddLoad() {
		return jpAddLoad;
	}


	public JPanel getJpLoadsTable() {
		return jpLoadsTable;
	}


	public SpinnerNumberModel getSnmRandomLoadNumber() {
		return snmRandomLoadNumber;
	}


	public JTextField getJtfLiftSpeed() {
		return jtfLiftSpeed;
	}


	public JTextField getJtfConveyorSpeed() {
		return jtfConveyorSpeed;
	}


	public JTextField getJtfSimulationSpeed() {
		return jtfSimulationSpeed;
	}


	public JTextArea getJtaStrategyDescription() {
		return jtaStrategyDescription;
	}

	
	public DefaultTableModel getDtmManualLoads() {
		return dtmManualLoads;
	}


	/**
	 * @return the jtfLoadName
	 */
	public JTextField getJtfLoadName() {
		return jtfLoadName;
	}


	/**
	 * @return the jtfClassOfGood
	 */
	public JTextField getJtfClassOfGood() {
		return jtfClassOfGood;
	}


	/**
	 * @return the jtfArrivalTime
	 */
	public JTextField getJtfArrivalTime() {
		return jtfArrivalTime;
	}


	/**
	 * @return the jlSimulationSpeedUnitText
	 */
	public JLabel getJlSimulationSpeedUnitText() {
		return jlSimulationSpeedUnitText;
	}


	/**
	 * @return the jcbOut
	 */
	public JCheckBox getJcbOut() {
		return jcbOut;
	}


	/**
	 * @return the jcbIn
	 */
	public JCheckBox getJcbIn() {
		return jcbIn;
	}


	/**
	 * @return the jcbStore
	 */
	public JCheckBox getJcbStore() {
		return jcbStore;
	}


	/**
	 * @return the jtManualLoads
	 */
	public JTable getJtManualLoads() {
		return jtManualLoads;
	}
}
